<?php

namespace Library\Auth;

class Session {

	private static $_instance = null;
	
	public static function getSession() {
		if( self::$_instance === null ) {
			self::$_instance = new Session();
		}
		return self::$_instance;
	}
	
	private $_user = null;
	
	private function __construct() {
		$this->_user = $this->_getUser();
	}
	
	public function getUser() {
		return $this->_user;
	}
	
	public function setUser( $user ) {
		$this->_user = $user;
		$sessionConf = \Library\Config::get( 'session' );
		session_start( $sessionConf['name'] );
		$_SESSION['user'] = $user;
		session_write_close();
		return $this;
	}
	
	public function isAuthenticated() {
		return $this->_user !== null;
	}
	
	private function _getUser() {
	
		if( $_SESSION['user'] ) {
			return $_SESSION['user'];
		}

		$sessionConf = \Library\Config::get( 'session' );
		$name = $sessionConf['remembrance']['name'];
		
		if( $this->_authenticate( $name ) ) {
			return $_SESSION['user'];
		}
		
		setCookie($name, '', strtotime( '-1 hour' ));
		return null;
	}
	
	private function _authenticate( $name ) {

		if( !isset($_COOKIE[$name]) ) {
			return false;
		}

		$sessionConf = \Library\Config::get( 'session' );
		
		/**
		* Step 1 : Check session existence
		*/
		$data = unserialize( $_COOKIE[$name] );
		if( !$data['key'] ) {
			return false;
		}

		try {
			$session = _q()->get1( 'users_sessions', array( 
				'session_id' => $data['id'],
				'auth_key' => $data['key']
			) );
		}
		catch( \Exception $e ) {
			return false;
		}
		
		if( strtotime($session['creation_time']) + $sessionConf['remembrance']['ttl'] < time() ) {
			_q()->del( 'users_sessions', array( 'session_id' => $session['session_id'] ) );
			return false;
		}

		/**
		* Step 2 : Check user
		*/
		try {
			$user = \Bean\User::get( $session['user_id'] );
		}
		catch( \Exception $e ) {
			return false;
		}

		/**
		* Step 3 : Connect user
		*/
		$auth = new User( $user );
		$auth->connect();
		
		/**
		* Step 4 : Store in session
		*/
		$this->setUser( $user );
		
		return true;
	}
	
	public function createRemembranceCookie( $password ) {

		if( !$this->isAuthenticated() ) {
			return $this;
		}

		$user = $this->_user;
		
		$authKey = openssl_random_pseudo_bytes( 10 );
		$sessionId = _q()->set1( 'users_sessions', 
			array( 
				'user_id' => $user->getUserId(),
				'auth_key' => $authKey,
				'creation_time' => _now()
			) );
		
		$sessionConf = \Library\Config::get( 'session' );
		
		setCookie( $sessionConf['remembrance']['name'], 
			serialize( array( 'id' => $sessionId, 'key' => $authKey ) ), 
			time() + $sessionConf['remembrance']['ttl'] );

		return $this;
	}
	
	public function deleteRemembranceCookie() {
	
		$sessionConf = \Library\Config::get( 'session' );
		setCookie( $sessionConf['remembrance']['name'], '', strtotime( '-1 hour' ) );
		return $this;
	}
	
}
